package com.yonyou.wdt.job;

import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yonyou.wdt.entity.OpenApiURLEnum;
import com.yonyou.wdt.entity.QueryDto;
import com.yonyou.wdt.job.config.BaseConfig;
import com.yonyou.wdt.qimenmodel.qimencloud.api.scenehu3cgwt0tc.request.WdtStockInDtlQueryRequest;
import com.yonyou.wdt.qimenmodel.qimencloud.api.scenehu3cgwt0tc.request.WdtStockinOrderQueryRefundRequest;
import com.yonyou.wdt.qimenmodel.qimencloud.api.scenehu3cgwt0tc.response.WdtStockInDtlQueryResponse;
import com.yonyou.wdt.qimenmodel.qimencloud.api.scenehu3cgwt0tc.response.WdtStockinOrderQueryRefundResponse;
import com.yonyou.wdt.service.YonsuiteService;
import com.yonyou.wdt.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

@Component
public class WdtQmRefundToYsSaleOutRedJobNew extends BaseConfig {

	private static final Logger logger = LoggerFactory.getLogger(WdtQmRefundToYsSaleOutRedJobNew.class);
	private final WdtConfigProperties configProperties;
	@Resource
	private YonsuiteService yonsuiteService;
	private static final String JOB_CLASS="maoEr006";
	@Autowired
	public WdtQmRefundToYsSaleOutRedJobNew(WdtConfigProperties configProperties) {
		this.configProperties = configProperties;
	}
	
	@XxlJob("WdtQmRefundToYsSaleOutRedJobNew")
	public ReturnT<String> wdtQmRefundToYsSaleOutRedJob(String params) throws Exception {
		String param = XxlJobHelper.getJobParam();
		Map<String, Object> map = new HashMap<>();
		if (param != null && !"".equals(param)) {
			List<String> timeRange = Arrays.asList(param.split("\\|"));
			if (timeRange.size() == 2) {
				map.put("Start", timeRange.get(0));
				map.put("End", timeRange.get(1));
			} else {
				map.put("stockin_no", timeRange.get(0));
			}
		} else {
			// 默认查询前一天的数据
			map.put("Start", DateUtils.getStartDateBy10m());
			map.put("End", DateUtils.getEndDateBy10m());
		}
		String dateStr = null;
		if (map.get("stockin_no")==null){
			dateStr = map.get("Start").toString() + map.get("End").toString();
		}
		// 处理相关业务
		QueryDto dto = new QueryDto();
		dto.setTenantId(getYsTenantId());
		dto.setAppKey(getYsAppKey());
		dto.setAppSecret(getYsAppSecret());
		// 获取YS系统租户动态域名信息
		ReturnT<String> isReturn2 = getYsDynamicDomainName(JOB_CLASS,dto);
		// 域名获取失败
		if (isReturn2 != null) return isReturn2;
		try {
			// 根据客户查询旺店通店铺配置信息
			//自定义档案列表查询
			HashMap<String, String> custData = YsQueryUtil.getFhdpDef(dto,yonsuiteService);
			ArrayList<String> collect = new ArrayList<>();
			for (String s : custData.keySet()) {
				collect.add(custData.get(s));
			}
			String replace = collect.toString().replace("[", "").replace("]","").replace(" ","");
			map.put("shop_nos", replace);
				List<JSONObject> responseList = sendWdtByQm(map);
				// 解析数据，组装YS请求参数
				if (!responseList.isEmpty()) {
					ArrayList<Map<String, Object>> ysSaveParamList = new ArrayList<>();
					for (JSONObject jsonObject : responseList) {
						Map<String, Object> ysSaveParam = assembleYsParams(jsonObject, dto);
						if (null != ysSaveParam) {
							ysSaveParamList.add(ysSaveParam);
						}
					}
					logger.info("当前时间段：{}至{} 需要同步到YS销售出库（红字）数据有：{}条", map.get("Start"), map.get("End"), ysSaveParamList.size());
					// 调用YS接口保存数据
					int index = 1;  // 记录执行次数处理接口调用频率问题
					for (Map<String, Object> paramMap : ysSaveParamList) {
						JSONObject response = yonsuiteService.saleOutMergeSave(paramMap, dto);
						String wdtCode = JSONUtil.parseObj(paramMap.get("data")).getStr("code");
						if (null != response && "200".equals(response.getStr("code")) && 1==(response.getJSONObject("data").getInt("sucessCount"))) {
							logger.info("旺店通销售退货入库单保存YS销售出库（红字）成功");
							JSONObject dataJson = response.getJSONObject("data") != null ? response.getJSONObject("data") : new JSONObject();
							String ysCode = JSONUtil.parseObj(dataJson.getJSONArray("infos").get(0)).getStr("code");
							InsertLogger(JOB_CLASS,wdtCode,"1","旺店通销售退货入库单"+wdtCode+"保存YS销售出库（红字）"+ysCode+"成功");
						} else {
							logger.error("旺店通销售退货入库单保存YS销售出库（红字）失败：{}", response.getJSONObject("data").getOrDefault("messages", ""));
							InsertLogger(JOB_CLASS,wdtCode,"0","旺店通销售退货入库单"+wdtCode+"保存YS销售出库（红字）失败："+response.getJSONObject("data").getOrDefault("messages", "").toString());
						}
						// 处理YS接口调用频率问题
						this.APICurrentLimiting(OpenApiURLEnum.SALE_STOCK_OUT_MERGE_SOURCE_SAVE,39);

					}
				}
		} catch (Exception e) {
			logger.error("Error occurred", e);
			logger.error("旺店通销售退货入库单同步YS销售出库（红字）失败，{}", e.getMessage());
			InsertLogger(JOB_CLASS,null,"0","旺店通销售退货入库单保存YS销售出库（红字）失败："+e.getMessage());
			return ReturnT.FAIL;
		}
		logger.info("  --  旺店通销售退货入库单同步YS销售出库（红字）任务执行完成  --  ");
		return ReturnT.SUCCESS;
	}
	
	/**
	 * @return
	 * @Author Huangwb
	 * @Description 组装YS请求数据
	 * @Date 14:34 2023/5/17
	 * @Param
	 **/
	private Map<String, Object> assembleYsParams(JSONObject jsonObject, QueryDto dto) throws Exception {
		//退换管理查询
		String refundNo=jsonObject.getStr("refund_no");
		List<JSONObject> wdtRefundInfo=getWdtRefundInfo(refundNo);
		Map<String, Object> data = new HashMap<>();
		Map<String, Object> body = new HashMap<>();
		// ==========主表============
		body.put("mergeSourceData",true);

		body.put("warehouse", jsonObject.getStr("warehouse_no")); // 仓库id或编码
		String orderNo = jsonObject.getStr("order_no");
		body.put("vouchdate", jsonObject.getStr("check_time")); // 单据日期
		body.put("code", orderNo);
		body.put("_status", "Insert");
		JSONArray items = jsonObject.getJSONArray("details_list");
		body.put("cLogisticsBillNo", jsonObject.getStr("logistics_no"));
		JSONArray details = new JSONArray();
		//查询销售退货单
		HashMap<String, Object> map = new HashMap<>();
		//map.put("code",jsonObject.getStr("refund_no"));
		if (wdtRefundInfo.isEmpty() || StringUtils.isBlank(wdtRefundInfo.get(0).getStr("src_no"))){
			return null;
		}
		map.put("code",wdtRefundInfo.get(0).getStr("src_no"));
		ArrayList<JSONObject> ysSaleReturnList = getYsSaleReturnList(map, dto);
		if (ysSaleReturnList.isEmpty()){
			return null;
		}
		// ==========子表============
		for (Object element : items) {
			JSONObject item = (JSONObject) element;
			JSONObject detailJSON = new JSONObject();
			detailJSON.put("_status","Insert");
			detailJSON.put("qty",item.getBigDecimal("num").negate());
			detailJSON.put("batchno", StringUtils.isBlank(item.getStr("batch"))?"202412":item.getStr("batch"));
			detailJSON.put("invaliddate", StringUtils.isBlank(item.getStr("expire_date")) || item.getStr("expire_date").substring(0,10).equals("0000-00-00")?"2027-12-31":item.getStr("expire_date"));
			for (JSONObject ysJsonObj : ysSaleReturnList) {
				if (ysJsonObj.getStr("productCode").equals(item.getStr("goods_no"))){
					detailJSON.put("sourceid",ysJsonObj.getStr("id"));
					detailJSON.put("sourceautoid",ysJsonObj.getStr("saleReturnDetailId"));
					detailJSON.put("makeRuleCode","salereturnTosalesout");
					details.add(detailJSON);
				}
			}
		}
		HashMap<String, Object> defHashMap = new HashMap<>();
		defHashMap.put("maoer04",jsonObject.getStr("logistics_name"));
		defHashMap.put("maoer03",jsonObject.getStr("shop_no"));
		defHashMap.put("maoer05",orderNo);
		body.put("salesOutDefineCharacter",defHashMap);
		String bustyp="A30001";
		body.put("bustype", bustyp); // 交易类型id或编码
		body.put("details", details);
		/*body.put("resubmitCheckKey","11121");
		// 测试用过一些数据，可能会重新同步，防止幂等相同
		ReSubmitUtil.resubmitCheckKey(body);*/
		data.put("data", body);
		return data;
	}

	private List<JSONObject> getWdtRefundInfo(String refundNo) {
		// 创建旺店通采购入库单查询请求实体对象
		// 单据状态：10=已取消；20=编辑中；30=待审核；37=待质检；40=质检确认；80=已完成
		//单据类别 1采购入库, 2调拨入库,  4盘盈入库, 5生产入库, 6调拨入库, 7保修入库, 8纠错入库, 9初始化入库 10 预入库 11 JIT退货入库 12 委外入库
		//otherInStockRequest.setOrder_type(type);
		int pageSize = 50;
		int pageIndex = 0;
		List<JSONObject> transferInList = new ArrayList<>();
		// 旺店通请求客户端对象创建
		WdtClient client = new WdtClient(configProperties.getSid(), configProperties.getKey(), configProperties.getSecret(), configProperties.getUrl());
		HashMap<String, Object> map = new HashMap<>();
		map.put("refund_no",refundNo);
		// 循环查询满足条件的所有数据
		while (true) {
			map.put("page_no",pageIndex);
			map.put("page_size",pageSize);
			// 调用旺店通接口查询调拨入库单数据
			String execute = client.execute("refund_query.php", map);
			JSONObject response = JSONUtil.parseObj(execute);
			if (null != response && response.getInt("code") == 0) {
				int totalCount = response.getInt("total_count");
				// 旺店通接口查询频率问题处理
				JSONArray jsonArray = response.getJSONArray("refunds");
				if (!jsonArray.isEmpty()){
					List<JSONObject> list = JSONUtil.toList(jsonArray, JSONObject.class);
					transferInList.addAll(list);
				}
				Integer page=pageIndex+1;
				if (totalCount < page * pageSize) {
					break;
				} else {
					pageIndex++;
				}
			} else {
				if (response != null) {
					logger.error("查询旺店通退换单异常：{}，请重试", response.getStr("message"));
					return null;
				} else {
					logger.error("查询旺店通退换单异常：旺店通接口返回数据为空，请重试");
					return null;
				}
			}
			this.APICurrentLimiting("refund_query.php",59);

		}
		return transferInList;
	}

	private List getYsSaleOrderList(JSONObject value, QueryDto dto) throws Exception {
		HashMap<String, Object> queryMap = new HashMap<>();
		queryMap.put("pageSize", 100);
		queryMap.put("isSum", false);
		// queryMap.put("open_vouchdate_begin", map.get("Start"));  // 开始时间
		// queryMap.put("open_vouchdate_end", map.get("End"));  // 结束时间
		HashMap<String, Object> simpleVosMap = new HashMap<>();
		simpleVosMap.put("field", "id");
		simpleVosMap.put("op", "eq");
		simpleVosMap.put("value1", value.getStr("saleReturnDetails_firstsourceid"));
		ArrayList<Map<String, Object>> simpleVosList = new ArrayList<>();
		simpleVosList.add(simpleVosMap);
		queryMap.put("simpleVOs", simpleVosList);
		int pageIndex = 1;
		ArrayList<JSONObject> purList = new ArrayList<>();
		int errorIndex = 0;
		while (true) {
			queryMap.put("pageIndex", pageIndex);
			JSONObject purJsonResponse = yonsuiteService.saleOrderList(queryMap, dto);
			if ("200".equals(purJsonResponse.getStr("code"))) {
				if (null != purJsonResponse.getJSONObject("data") && null != purJsonResponse.getJSONObject("data").getJSONArray("recordList")) {
					JSONArray purJsonArray = purJsonResponse.getJSONObject("data").getJSONArray("recordList");
					for (Object pur : purJsonArray) {
						JSONObject purJson = (JSONObject) pur;
						purList.add(purJson);
					}
				}
				if (purJsonResponse.getJSONObject("data").getInt("pageCount") <= pageIndex) {
					break;
				}
				// 接口执行频率问题处理
				this.APICurrentLimiting(OpenApiURLEnum.SALES_ORDER_LIST,59);
				pageIndex++;
			} else {
				if (errorIndex < 10) {
					errorIndex++;
					logger.error("查询YS销售订单单第：{}，页失败：{},延迟一秒查询", pageIndex, purJsonResponse.getOrDefault("message", "接口未返回数据"));
					Thread.sleep(1000);
				} else {
					// 多次失败， 退出定时任务排查原因
					logger.error("YS销售退货单同步旺店通售后单定时任务多次执行失败，此次任务作废");
					return new ArrayList<>();
				}
			}
		}
		return purList;
	}

	/**
	 * @return
	 * @Author Huangwb
	 * @Description 查询YS销售退货单列表
	 * @Date 10:36 2023/5/12
	 * @Param
	 **/
	private ArrayList<JSONObject> getYsSaleReturnList(Map<String, Object> map, QueryDto dto) throws Exception {
		HashMap<String, Object> queryMap = new HashMap<>();
		queryMap.put("pageSize", 100);
		queryMap.put("isSum", false);
		// queryMap.put("open_vouchdate_begin", map.get("Start"));  // 开始时间
		// queryMap.put("open_vouchdate_end", map.get("End"));  // 结束时间
		queryMap.put("saleReturnStatus", "CONFIRMSALERETURNORDER");//单据状态, SUBMITSALERETURN:开立、CONFIRMSALERETURNORDER:已确认、SALERETURNING:退货中、ENDSALERETURN:已审核、OPPOSESALERETURN:已驳回、
		queryMap.put("saleReturnSourceType", "DELIVERYEND");//退货类型, NONE:无来源、DELIVERYEND:销售出库单、ORDER:销售订单
		queryMap.put("code", map.get("code").toString());
		int pageIndex = 1;
		ArrayList<JSONObject> purList = new ArrayList<>();
		int errorIndex = 0;
		while (true) {
			queryMap.put("pageIndex", pageIndex);
			JSONObject purJsonResponse = yonsuiteService.saleReturnList(queryMap, dto);
			if ("200".equals(purJsonResponse.getStr("code"))) {
				if (null != purJsonResponse.getJSONObject("data") && null != purJsonResponse.getJSONObject("data").getJSONArray("recordList")) {
					JSONArray purJsonArray = purJsonResponse.getJSONObject("data").getJSONArray("recordList");
					for (Object pur : purJsonArray) {
						JSONObject purJson = (JSONObject) pur;
						purList.add(purJson);
					}
				}
				if (purJsonResponse.getJSONObject("data").getInt("pageCount") <= pageIndex) {
					break;
				}
				// 接口执行频率问题处理
				this.APICurrentLimiting(OpenApiURLEnum.SALE_STOCK_RETURN_QUERY,59);
				pageIndex++;
			} else {
				if (errorIndex < 10) {
					errorIndex++;
					logger.error("查询YS销售退货单第：{}，页失败：{},延迟一秒查询", pageIndex, purJsonResponse.getOrDefault("message", "接口未返回数据"));
					Thread.sleep(1000);
				} else {
					// 多次失败， 退出定时任务排查原因
					logger.error("YS销售退货单查询失败，此次任务作废");
					return new ArrayList<>();
				}
			}
		}
		return purList;
	}

	private List<JSONObject> sendWdtByQm(Map<String, Object> map) throws InterruptedException {
		List<JSONObject> resList = new ArrayList<>();
		com.yonyou.wdt.qimenmodel.qimencloud.api.DefaultQimenCloudClient client = new com.yonyou.wdt.qimenmodel.qimencloud.api.DefaultQimenCloudClient(configProperties.getQmServerUrl(), configProperties.getQmAppKey(), configProperties.getQmAppSecret(), "json");
		Integer realityPageNo = 0;
		map.put("page_no", realityPageNo.toString());
		map.put("page_size", "100");
		boolean hasNext = true;
		//总页数
		Integer totalPage = 0;
		//总条数
		Integer total_count = 0;
		while (hasNext) {
			map.put("page_no", realityPageNo.toString());
			WdtStockinOrderQueryRefundRequest req = this.setModel(map, configProperties.getQmTargetAppKey(), configProperties.getSid());
			WdtStockinOrderQueryRefundResponse res = null;
			try {
				res = client.execute(req);
			} catch (com.yonyou.wdt.qimenmodel.taobao.api.ApiException e) {
				throw new RuntimeException(e);
			}
			JSONObject saleOutJson = JSONUtil.parseObj(res.getBody()).getJSONObject("response");
			if ("0".equals(saleOutJson.getStr("errorcode"))) {
				//判断分页
				if (realityPageNo == 0) {
					total_count = saleOutJson.getInt("total_count", 0);
					totalPage = total_count % 100 == 0 ? total_count / 100 : total_count / 100 + 1;
				}
				//每页订单列表
				JSONArray orderArray = saleOutJson.getJSONArray("stockin_list");
				if (orderArray.size() > 0) {
					//resList.addAll(JSONUtil.toList(orderArray, JSONObject.class));
					List<JSONObject> list = JSONUtil.toList(orderArray, JSONObject.class);
					for (JSONObject entries : list) {
						ArrayList<JSONObject> dtlList = new ArrayList<>();
						HashMap<String, Object> stringObjectHashMap = new HashMap<>();
						String stockOutNo = entries.getStr("order_no");
						stringObjectHashMap.put("stockin_no",stockOutNo);
						Boolean flag=true;
						Integer dtlTotalCount=0;
						Integer dtlTotalPage=0;
						Integer dtlRealityPageNo = 0;
						while (flag){
							stringObjectHashMap.put("page_no",dtlRealityPageNo.toString());
							stringObjectHashMap.put("page_size",100);
							WdtStockInDtlQueryRequest dtlReq = this.setStockInDtlModel(stringObjectHashMap, configProperties.getQmTargetAppKey(), configProperties.getSid());
							WdtStockInDtlQueryResponse dtlRes = null;
							try {
								dtlRes = client.execute(dtlReq);
							} catch (com.yonyou.wdt.qimenmodel.taobao.api.ApiException e) {
								throw new RuntimeException(e);
							}
							JSONObject dtlJson = JSONUtil.parseObj(dtlRes.getBody()).getJSONObject("response");
							if ("0".equals(dtlJson.getStr("errorcode"))) {
								//判断分页
								if (dtlRealityPageNo == 0) {
									dtlTotalCount = dtlJson.getInt("total_count", 0);
									dtlTotalPage = dtlTotalCount % 100 == 0 ? dtlTotalCount / 100 : dtlTotalCount / 100 + 1;
								}
								//每页订单列表
								JSONArray dtlJosn = dtlJson.getJSONArray("stockin_batch_detail");
								dtlList.addAll(JSONUtil.toList(dtlJosn,JSONObject.class));
							}else {
								InsertLogger(JOB_CLASS,stockOutNo, "0", "旺店通入库批次接口查询失败" + dtlJson.getStr("message"));
								break;
							}
							this.APICurrentLimiting("wdt.stockin.batch.detail",59);
							if (dtlTotalPage > dtlRealityPageNo + 1) {
								dtlRealityPageNo += 1;
							} else {
								flag = false;
							}
						}


						JSONArray jsonArray = entries.getJSONArray("details_list");
						JSONArray newDetail = new JSONArray();
						for (Object obj : jsonArray) {
							JSONObject entries1 = JSONUtil.parseObj(obj);
							Optional<JSONObject> any = dtlList.stream().filter(o -> o.getStr("goods_no").equals(entries1.getStr("goods_no"))).findAny();
							if (any.isPresent()){
								entries1.set("batch",any.get().getStr("batch"));
								String substring = any.get().getStr("expire_date").substring(0, 10);
								if (!substring.equals("0000-00-00")){
									entries1.set("expire_date", substring);
								}else {
									entries1.set("expire_date", "");
								}
							}

							newDetail.add(entries1);
						}
						entries.set("details_list",newDetail);
						resList.add(entries);
					}
				}
				//判断分页
				if (realityPageNo == 0) {
					total_count = saleOutJson.getInt("total_count", 0);
					totalPage = total_count % 100 == 0 ? total_count / 100 : total_count / 100 + 1;
				}
				if (totalPage > realityPageNo + 1) {
					realityPageNo += 1;
				} else {
					hasNext = false;
				}
			} else {
				InsertLogger(JOB_CLASS,null, "0", "旺店通退货入库接口查询失败" + saleOutJson.getStr("sub_message"));
				break;
			}
		}
		return resList;
	}

	public WdtStockinOrderQueryRefundRequest setModel(Map param, String targetAppKey, String sid) {
		WdtStockinOrderQueryRefundRequest req = new WdtStockinOrderQueryRefundRequest();
		//旺店通的奇门appkey
		req.setTargetAppKey(targetAppKey);
		//旺店通erp的卖家账号
		req.setSid(sid);
		String startTime = MapUtil.getStr(param, "Start");
		if (StringUtils.isNotBlank(startTime)) {
			req.setStartTime(startTime);
		}
		String endTime = MapUtil.getStr(param, "End");
		if (StringUtils.isNotBlank(endTime)) {
			req.setEndTime(endTime);
		}
		String stockinNo = MapUtil.getStr(param, "stockin_no");
		if (StringUtils.isNotBlank(stockinNo)) {
			req.setStockinNo(stockinNo);
		}
		String srcOrderNo = MapUtil.getStr(param, "src_order_no");
		if (StringUtils.isNotBlank(srcOrderNo)) {
			req.setSrcOrderNo(srcOrderNo);
		}
		String shop_no = MapUtil.getStr(param, "shop_no");
		if (StringUtils.isNotBlank(shop_no)) {
			req.setShopNo(shop_no);
		}
		if (param.containsKey("page_no")) {
			req.setPageNo(MapUtil.getLong(param, "page_no"));
		}
		if (param.containsKey("page_size")) {
			req.setPageSize(MapUtil.getLong(param, "page_size"));
		}
		if (param.containsKey("status")) {
			req.setStatus(MapUtil.getLong(param, "status"));
		}
		if (param.containsKey("shop_nos")) {
			req.setShopNos(MapUtil.getStr(param, "shop_nos"));
		}
		return req;
	}



}
